package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.repository.CartRepository;
import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.config.interceptor.UserAuthContext;
import com.atguigu.gmall.common.constant.RedisConstant;
import com.atguigu.gmall.common.execption.GmallException;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.MathUtil;
import com.atguigu.gmall.feign.product.SkuInfoFeginClient;
import com.atguigu.gmall.model.cart.entity.CartInfo;
import com.atguigu.gmall.model.cart.entity.UserAuth;
import com.atguigu.gmall.model.cart.vo.AddCartVO;
import com.atguigu.gmall.model.product.entity.SkuInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.Duration;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements CartService {

    @Autowired
    SkuInfoFeginClient skuInfoFeginClient;

    @Autowired
    CartRepository cartRepository;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    UserAuthContext userAuthContext;


    @Override
    public AddCartVO addCart(String key, Long skuId, Integer skuNum) {
        AddCartVO addCartVO = new AddCartVO();
        //构建CartInfo对象存到redis
        SkuInfo skuInfo = skuInfoFeginClient.getSkuInfo(skuId).getData();
        CartInfo cartInfo = buildCartInfoBySkuInfo(skuInfo);
        cartInfo.setSkuNum(skuNum);
        //先查看redis有没有此商品，有的话就是增加数量，没有就是新增
        if (cartRepository.isExit(key, skuId)) {
            //如果redis存在
            CartInfo cartItem = cartRepository.one(key, skuId);
            cartItem.setSkuNum(cartItem.getSkuNum() + skuNum);
            cartRepository.save(key, skuId, cartItem);
        } else {
            //添商品时判断商品项数量是否超过上限
            Long size = cartRepository.size(key);
            if (size + 1 > RedisConstant.REDIS_CART_ITEM_MAX_NUM) {
                throw new GmallException(ResultCodeEnum.CART_ITEM_NUM_ERROR);
            }
            cartRepository.save(key, skuId, cartInfo);
        }
        SkuInfo sku = buildSkuInfoByCartInfo(cartInfo);
        addCartVO.setSkuInfo(sku);
        addCartVO.setSkuNum(cartInfo.getSkuNum());
        //获取UserAuth
        UserAuth userAuth = userAuthContext.getUserAuth();
        if (userAuth.getUserId() == null) {
            //如果用户id为空说明没有登录
            //查看当前key的过期时间，如果是-1说明没有设置
            Long ttlByKey = cartRepository.getTtlByKey(key);
            if (ttlByKey < 0) {
                //设置一年过期时间，与前端同步
                cartRepository.setTtl(key, Duration.ofDays(365));
            }
        }
        return addCartVO;
    }

    @Override
    public List<CartInfo> getCartList(String key) {
        UserAuth userAuth = userAuthContext.getUserAuth();
        if (userAuth.getUserId() != null && StringUtils.hasText(userAuth.getUserTempId())) {
            //如果临时id和用户id都有的情况下，合并临时id的商品到订单id
            List<CartInfo> tempCart = cartRepository.list(RedisConstant.REDIS_CART_KEY + userAuth.getUserTempId());
            if (tempCart != null && tempCart.size() > 0) {
                tempCart.forEach(item -> {
                    //合并购物车，懒加载，用户点击购物车列表，如果临时购物车有数据就加入用户购物车
                    log.info("正在合并，把{}数据合并到{}", RedisConstant.REDIS_CART_KEY + userAuth.getUserTempId(), key);
                    try {
                        //循环放进去
                        addCart(key, item.getSkuId(), item.getSkuNum());
                    } catch (GmallException exception) {
                        throw new GmallException(ResultCodeEnum.CART_ITEM_MERGE_ERROR);
                    }
                    //放一个删除一个
                    cartRepository.delete(RedisConstant.REDIS_CART_KEY + userAuth.getUserTempId(), item.getSkuId().toString());
                });
            }
        }
        //最后查询一下列表
        List<CartInfo> list = cartRepository.list(key);
        list.stream().parallel()//开启并行流
                .forEach(item -> {
                    //懒加载，用户点击购物车的时候，发现商品价格变化了就改变
                    BigDecimal skuPrice = item.getSkuPrice();
                    //远程调用
                    BigDecimal price = skuInfoFeginClient.getPrice(item.getSkuId()).getData();
                    if (!MathUtil.bigDecimalEquals(skuPrice, price)) {
                        item.setSkuPrice(price);
                    }
                });
        return list;
    }

    @Override
    public void deleteCart(String key, Long skuId) {
        cartRepository.delete(key, skuId.toString());
    }

    @Override
    public void addToCart(String key, Long skuId, Integer num) {
        CartInfo cartInfo = cartRepository.one(key, skuId);
        cartInfo.setSkuNum(cartInfo.getSkuNum() + num);
        cartRepository.save(key, skuId, cartInfo);
    }

    @Override
    public void checkCart(String key, Long skuId, Integer check) {
        CartInfo cartInfo = cartRepository.one(key, skuId);
        cartInfo.setIsChecked(check);
        cartRepository.save(key, skuId, cartInfo);
    }

    @Override
    public void deleteChecked(String key) {
        List<CartInfo> list = cartRepository.list(key);
        String[] skuIds = list.stream()
                .filter(item -> item.getIsChecked() == 1)
                .map(item -> item.getSkuId().toString())
                .toArray(String[]::new);
        cartRepository.delete(key, skuIds);


    }

    private SkuInfo buildSkuInfoByCartInfo(CartInfo cartInfo) {
        SkuInfo skuInfo = new SkuInfo();
        skuInfo.setId(cartInfo.getSkuId());
        skuInfo.setSkuName(cartInfo.getSkuName());
        skuInfo.setSkuDefaultImg(cartInfo.getImgUrl());
        return skuInfo;
    }

    private CartInfo buildCartInfoBySkuInfo(SkuInfo skuInfo) {
        CartInfo cartInfo = new CartInfo();
        cartInfo.setSkuId(skuInfo.getId());
        cartInfo.setCartPrice(skuInfo.getPrice());
        cartInfo.setSkuPrice(skuInfo.getPrice());
        cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
        cartInfo.setSkuName(skuInfo.getSkuName());
        cartInfo.setIsChecked(1);
        cartInfo.setCreateTime(new Date());
        cartInfo.setUpdateTime(new Date());
        return cartInfo;
    }

    @Override
    public String decisionKey(UserAuth userAuth) {
        return RedisConstant.REDIS_CART_KEY + (userAuth.getUserId() != null ? userAuth.getUserId().toString()
                : userAuth.getUserTempId());
    }



    @Override
    public List<CartInfo> getUserCartList(String key) {
        List<CartInfo> list = cartRepository.list(key);
        return list;
    }

    @Override
    public List<CartInfo> checkedList(String key) {
        List<CartInfo> cartInfoList = cartRepository.list(key)
                .stream()
                .filter(item -> item.getIsChecked() == 1)
                .collect(Collectors.toList());
        return cartInfoList;
    }


}
